﻿using System;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Security.Cryptography;
using Microsoft.SharePoint.Administration;
using ServBus.ListForm2010.Utility;

namespace ServBus.ListForm2010.License
{
    internal class LicenseContainer
    {
        private static readonly byte[] _verifyKey = { 0x6, 0x2, 0x0, 0x0, 0x0, 0xA4, 0x0, 0x0, 0x52, 0x53, 0x41, 0x31, 0x0, 0x4, 0x0, 0x0, 0x1, 0x0, 0x1, 0x0, 0xFB, 0x36, 0x16, 0x3E, 0xB5, 0x84, 0x6E, 0x11, 0x2A, 0xDB, 0x26, 0x6, 0x21, 0x25, 0xEB, 0x49, 0xED, 0xC5, 0x8E, 0x45, 0x6, 0x6F, 0x69, 0x1C, 0x3, 0x38, 0x67, 0x65, 0x75, 0xE5, 0xC, 0x3F, 0x1F, 0xD5, 0x6E, 0xF3, 0x8E, 0x83, 0x6F, 0x2E, 0x8, 0x5, 0x1D, 0x3E, 0xCA, 0x7, 0x3, 0x7C, 0x2E, 0x9C, 0x59, 0x20, 0x6A, 0x7E, 0x49, 0x6E, 0x92, 0x5F, 0x24, 0x3C, 0x39, 0xD8, 0xC2, 0x4B, 0x4F, 0xD6, 0xA4, 0x32, 0x65, 0xB4, 0xC6, 0x0, 0x40, 0xFB, 0x63, 0xB1, 0x14, 0xFE, 0x8C, 0x45, 0x8D, 0x6, 0x23, 0xD3, 0xCC, 0x37, 0xFC, 0x4D, 0x75, 0xEA, 0xEC, 0x58, 0xA7, 0x52, 0x5C, 0x3B, 0x76, 0xA5, 0x23, 0x48, 0x34, 0xD4, 0x89, 0x5C, 0xCA, 0xCB, 0xE6, 0x9C, 0x96, 0x73, 0xEC, 0xBA, 0x5D, 0x8, 0xEA, 0x34, 0x85, 0xD6, 0xA7, 0xE, 0xD1, 0x8F, 0x20, 0xB5, 0x70, 0xF4, 0x4D, 0x89 };

        private LicenseContainer()
        { 
        }

        private static object _syncLock = new object();
        private static bool _isValid;
        private static License _license;

        public static License ProductLicense 
        {
            get 
            {
                EnsureLicense(false);
                return _license; 
            }
        }

        public static bool IsLicenseEmpty
        {
            get
            {
                //ErrorLog.Write("IsLicenseEmpty:in", System.Diagnostics.EventLogEntryType.Warning);
                EnsureLicense(false);                
                return _license == null;
            }
        }

        public static bool IsLicenseExpire
        {
            get
            {
                EnsureLicense(false);
                if (_license == null)
                    return false;
                return _license.ExpirationDate < DateTime.Now;
            }
        }

        public static bool IsLicenseValid
        {
            get
            {
                EnsureLicense(false);
                return _isValid;
            }
        }

        private static void EnsureLicense(bool force)
        {
            
            if (_license != null && !force)
            {
                //ErrorLog.Write("IsLicenseEmpty:out Directly", System.Diagnostics.EventLogEntryType.Warning);
                return;
            }
            lock (_syncLock)
            {
                try
                {
                    _isValid = false;
                    _license = null;
                    string licenseKey = Convert.ToString(SPFarm.Local.Properties[Constants.FARM_LICENSE_KEY]);

                    if (!string.IsNullOrEmpty(licenseKey))
                    {
                        //ErrorLog.Write("licenseKey is not null or empty:"+licenseKey, System.Diagnostics.EventLogEntryType.Warning);
                        byte[] bufferOrig = Convert.FromBase64String(licenseKey);
                        byte[] buffer = CryptoUtility.DecryptDES(bufferOrig);
                        byte[] licenseInfo = new byte[buffer.Length - 128];
                        byte[] verifyInfo = new byte[128];
                        Array.Copy(buffer, 0, licenseInfo, 0, licenseInfo.Length);
                        Array.Copy(buffer, licenseInfo.Length, verifyInfo, 0, 128);

                       // ErrorLog.Write("Deserialize licenseKey begin:"+licenseInfo.Length+","+licenseInfo.ToString(), System.Diagnostics.EventLogEntryType.Warning);
                        // Deserialize License
                        using (MemoryStream stream = new MemoryStream(licenseInfo))
                        {
                            IFormatter formatter = new BinaryFormatter();
                            _license = formatter.Deserialize(stream) as License;

                            //bool _licenseFlag = false;
                            //if (_license == null) _licenseFlag = true;
                            //ErrorLog.Write("IsLicenseEmpty:[_license=null?]" + _licenseFlag, System.Diagnostics.EventLogEntryType.Warning);
                            //ErrorLog.Write("_licenseExpirateDate = " + _license.ToString(), System.Diagnostics.EventLogEntryType.Warning);
                        }
                        
                        // Verify License
                        RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
                        rsa.ImportCspBlob(_verifyKey);
                        _isValid = rsa.VerifyData(licenseInfo, new SHA1CryptoServiceProvider(), verifyInfo);
                        //fake license
                        //_isValid = true;

                        //ErrorLog.Write("licenseUploadOk:"+_isValid, System.Diagnostics.EventLogEntryType.Information);
                    }
                }
                catch(Exception ex)
                {
                    ErrorLog.Write("Invalid License" + "\r\n" + ex.Message + "\r\n" + ex.StackTrace, System.Diagnostics.EventLogEntryType.Error);
                }
            }
        }

        public static void UpdateLicense()
        {
            EnsureLicense(true);
        }
    }
}
